/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2012-05-15     lgnq         first version.
 * 2012-05-28     bernard      change interfaces
 * 2013-02-20     bernard      use RT_SERIAL_RB_BUFSZ to define
 *                             the size of ring buffer.
 */

#ifndef __SERIAL_H__
#define __SERIAL_H__

#include <rtthread.h>
#include <stdint.h>

#define BAUD_RATE_2400                  2400
#define BAUD_RATE_4800                  4800
#define BAUD_RATE_9600                  9600
#define BAUD_RATE_19200                 19200
#define BAUD_RATE_38400                 38400
#define BAUD_RATE_57600                 57600
#define BAUD_RATE_115200                115200
#define BAUD_RATE_230400                230400
#define BAUD_RATE_460800                460800
#define BAUD_RATE_921600                921600
#define BAUD_RATE_2000000               2000000
#define BAUD_RATE_3000000               3000000

#define DATA_BITS_5                     5
#define DATA_BITS_6                     6
#define DATA_BITS_7                     7
#define DATA_BITS_8                     8
#define DATA_BITS_9                     9

#define STOP_BITS_1                     1
#define STOP_BITS_2                     2
#define STOP_BITS_3                     3
#define STOP_BITS_4                     4

#define PARITY_NONE                0
#define PARITY_ODD                 1
#define PARITY_EVEN                2

#define RT_SERIAL_EVENT_RX_IND          0x01    /* Rx indication */
#define RT_SERIAL_EVENT_TX_DONE         0x02    /* Tx complete   */
#define RT_SERIAL_EVENT_RX_DMADONE      0x03    /* Rx DMA transfer done */
#define RT_SERIAL_EVENT_TX_DMADONE      0x04    /* Tx DMA transfer done */
#define RT_SERIAL_EVENT_RX_TIMEOUT      0x05    /* Rx timeout    */

#define RT_SERIAL_DMA_RX                0x01
#define RT_SERIAL_DMA_TX                0x02

#define RT_SERIAL_RX_INT                0x01
#define RT_SERIAL_TX_INT                0x02

#define RT_SERIAL_ERR_OVERRUN           0x01
#define RT_SERIAL_ERR_FRAMING           0x02
#define RT_SERIAL_ERR_PARITY            0x03

#define RT_SERIAL_TX_DATAQUEUE_SIZE     2048
#define RT_SERIAL_TX_DATAQUEUE_LWM      30

#define UART_XMIT_RX    0
#define UART_XMIT_TX    1

struct serial_configure
{
    uint32_t baud_rate;

    uint8_t data_bits :4;
    uint8_t stop_bits :2;
    uint8_t parity    :2;
    uint8_t c_cc[3];
    uint16_t c_oflag;
};

struct rt_serial_device
{
    struct rt_device          parent;

    const struct rt_uart_ops *ops;
    struct serial_configure   config;

    struct rt_ringbuffer *rxrb;
    struct rt_ringbuffer *txrb;

    rt_wqueue_t rxwq;
    rt_wqueue_t txwq;

    uint8_t tx_started;
};
typedef struct rt_serial_device rt_serial_t;

/**
 * uart operators
 */
struct rt_uart_ops
{
    int (*configure)(rt_serial_t *serial, struct serial_configure *cfg);
    int (*control)(rt_serial_t *serial, int cmd, void* arg);

    int (*put)(rt_serial_t *serial, char c);
    int (*get)(rt_serial_t *serial);

    int (*init)(rt_serial_t *serial);
    void (*deinit)(rt_serial_t *serial);
    /* used to 'start RX/TX' or 'stop RX/Tx' ,
    (e.g call xmit_ctl(, UART_XMIT_RX, 1) start RX) */
    int (*xmit_ctl)(rt_serial_t *serial, int cmd, int arg);
};

void rt_hw_serial_isr(rt_serial_t *serial, int event);

int rt_hw_serial_register(rt_serial_t *serial,
                          const char  *name,
                          int         flag,
                          void        *usrdata);

#endif
